home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 2
/
Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso
/
Aminet
/
util
/
gnu
/
oleo_src.lha
/
src
/
io_utils.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-18
|
26KB
|
1,327 lines
/* Copyright (C) 1990 Free Software Foundation, Inc.
This file is part of Oleo, the GNU Spreadsheet.
Oleo is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
Oleo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Oleo; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "funcdef.h"
#include <stdio.h>
#include <ctype.h>
#include "sysdef.h"
#include "global.h"
#include "cell.h"
extern VOIDSTAR ck_malloc EXT1(size_t);
extern VOIDSTAR ck_realloc EXT2(void *,size_t);
extern double astof EXT1(char **);
extern long astol EXT1(char **);
extern unsigned short default_width;
extern CELLREF curow,cucol;
extern struct rng screen;
extern int default_fmt;
extern char numb_oflo[];
#ifdef TEST
extern void panic EXT1N(const char *);
#endif
char *bname[] = {
"#FALSE","#TRUE"
};
#ifndef ASM_INF
#ifdef __GNUC__
__asm(".globl ___plinf");
__asm("___plinf: .double 0rinf");
__asm(".globl ___neinf");
__asm("___neinf: .double 0r-inf");
__asm(".globl ___nan");
__asm("___nan: .double 0rnan");
#else
double __plinf = 1e500;
double __neinf = -1e500;
double __nan = 1e500/ -1e500;
#endif
#endif
const char nname[] = "#NOT_A_NUMBER";
const char iname[] = "#INFINITY";
const char mname[] = "#MINUS_INFINITY";
/* Slightly larger than the maximum exponent we ever expect to see */
#define BIGFLT 309
#ifdef TEST
char print_buf[1024*8];
#else
char print_buf[BIGFLT+20];
#endif
/* Functions, etc for dealing with cell contents being displayed
on top of other cells. */
struct slops {
int s_alloc,s_used;
struct s {
CELLREF row,clo,chi;
} s_b[1];
};
void
flush_slops FUN1(VOIDSTAR,where)
{
struct slops *s;
s=where;
if(s)
s->s_used=0;
}
int
find_slop FUN5(VOIDSTAR, where, CELLREF,r, CELLREF,c, CELLREF *,cclp, CELLREF *,cchp)
{
int n;
struct slops *s;
s= where;
if(!s)
return 0;
for(n=0;n<s->s_used;n++) {
if(s->s_b[n].row==r && s->s_b[n].clo<=c && s->s_b[n].chi>=c) {
*cclp=s->s_b[n].clo;
*cchp=s->s_b[n].chi;
return 1;
}
}
return 0;
}
void
kill_slop FUN4(VOIDSTAR,where, CELLREF,r, CELLREF,clo, CELLREF,chi)
{
int n;
struct slops *s;
s=where;
for(n=0;n<s->s_used;n++) {
if(s->s_b[n].row==r && s->s_b[n].clo==clo && s->s_b[n].chi==chi) {
--(s->s_used);
s->s_b[n]=s->s_b[s->s_used];
return;
}
}
}
void
set_slop FUN4(VOIDSTAR *,wherep, CELLREF,r, CELLREF,clo, CELLREF,chi)
{
int n;
struct slops **sp;
sp= (struct slops **)wherep;
if(!*sp) {
(*sp)=ck_malloc(sizeof(struct slops)+2*sizeof(struct s));
(*sp)->s_alloc=2;
(*sp)->s_used=1;
n=0;
} else {
n= (*sp)->s_used++;
if((*sp)->s_alloc==n) {
(*sp)->s_alloc=n*2;
(*sp)=ck_realloc((*sp),sizeof(struct slops)+n*2*sizeof(struct s));
}
}
(*sp)->s_b[n].row=r;
(*sp)->s_b[n].clo=clo;
(*sp)->s_b[n].chi=chi;
}
void
change_slop FUN6(VOIDSTAR,where, CELLREF,r, CELLREF,olo, CELLREF,ohi, CELLREF,lo, CELLREF,hi)
{
int n;
struct slops *s;
s= where;
for(n=0;n<s->s_used;n++) {
if(s->s_b[n].row==r && s->s_b[n].clo==olo && s->s_b[n].chi==ohi) {
s->s_b[n].clo=lo;
s->s_b[n].chi=hi;
return;
}
}
}
/* Stuff for dealing with width of columns */
/* This isn't the best place for it, but here it is. . . */
struct width {
struct width *prev,*next;
CELLREF w_low,w_high;
unsigned short wids[1];
};
struct width *wid_beg = 0;
struct width *wid_end = 0;
#define WID_BUF 1;
unsigned short
get_width FUN1(CELLREF, col)
{
struct width *my_width;
unsigned short n;
if(!wid_beg) {
n=default_width;
} else {
for(my_width=wid_beg;my_width && col>my_width->w_high;my_width=my_width->next)
;
if(!my_width || col<my_width->w_low)
n=default_width;
else {
if(col<=my_width->w_high) {
n=my_width->wids[col-my_width->w_low];
if(n==0)
n=default_width;
else
--n;
} else
n=default_width;
}
}
/* if(n>numc)
n=numc; */
return n;
}
/* This is like get_width, but it returns width+1, or zero if the width is default */
unsigned short
get_nodef_width FUN1(CELLREF, col)
{
struct width *my_width;
unsigned short n;
if(!wid_beg)
return 0;
for(my_width=wid_beg;my_width && col>my_width->w_high;my_width=my_width->next)
;
if(!my_width || col<my_width->w_low)
return 0;
if(col<=my_width->w_high) {
n=my_width->wids[col-my_width->w_low];
if(n==0)
return 0;
return n;
}
return 0;
}
void
set_width FUN2(CELLREF, col, unsigned short, wid)
{
struct width *my_wid;
struct width *tmp_wid;
if(!wid_beg) {
wid_beg=wid_end=(struct width *)ck_malloc(sizeof(struct width));
wid_beg->prev=0;
wid_beg->next=0;
wid_beg->w_low=col;
wid_beg->w_high=col;
wid_beg->wids[0]=wid;
return;
}
for(tmp_wid=wid_beg;tmp_wid;tmp_wid=tmp_wid->next)
if(col<=tmp_wid->w_high)
break;
if(!tmp_wid) {
if(wid_end->w_high==col-1) {
wid_end->w_high++;
wid_end=ck_realloc(wid_end,sizeof(struct width)+(wid_end->w_high-wid_end->w_low)*sizeof(unsigned short));
wid_end->wids[col-wid_end->w_low]=wid;
if(wid_end->prev)
wid_end->prev->next=wid_end;
else
wid_beg=wid_end;
} else {
my_wid=(struct width *)ck_malloc(sizeof(struct width));
my_wid->w_high=col;
my_wid->w_low=col;
my_wid->wids[0]=wid;
my_wid->next=0;
my_wid->prev=wid_end;
wid_end->next=my_wid;
wid_end=my_wid;
}
return;
}
if(col>=tmp_wid->w_low) {
tmp_wid->wids[col-tmp_wid->w_low]=wid;
return;
}
if(tmp_wid->prev && tmp_wid->prev->w_high==col-1) {
if(col+1==tmp_wid->w_low) {
struct width *w1,*w2;
w1=tmp_wid->prev;
w2=tmp_wid;
my_wid=(struct width *)ck_malloc(sizeof(struct width)+(w2->w_high-w1->w_low)*sizeof(unsigned short));
my_wid->prev=w1->prev;
my_wid->next=w2->next;
my_wid->w_high=w2->w_high;
my_wid->w_low=w1->w_low;
bcopy(w1->wids,&(my_wid->wids[0]),(1+w1->w_high-w1->w_low)*sizeof(unsigned short));
bcopy(w2->wids,&(my_wid->wids[w2->w_low-my_wid->w_low]),(1+w2->w_high-w2->w_low)*sizeof(unsigned short));
my_wid->wids[col-my_wid->w_low]=wid;
if(my_wid->prev)
my_wid->prev->next=my_wid;
else
wid_beg=my_wid;
if(my_wid->next)
my_wid->next->prev=my_wid;
else
wid_end=my_wid;
free(w1);
free(w2);
} else {
tmp_wid=tmp_wid->prev;
tmp_wid->w_high++;
tmp_wid=(struct width *)ck_realloc(tmp_wid,sizeof(struct width)+(tmp_wid->w_high-tmp_wid->w_low)*sizeof(unsigned short));
tmp_wid->wids[tmp_wid->w_high-tmp_wid->w_low]=wid;
tmp_wid->next->prev=tmp_wid;
if(tmp_wid->prev)
tmp_wid->prev->next=tmp_wid;
else
wid_beg=tmp_wid;
}
return;
}
if(col+1==tmp_wid->w_low) {
my_wid=(struct width *)ck_malloc(sizeof(struct width)+(1+tmp_wid->w_high-tmp_wid->w_low)*sizeof(unsigned short));
my_wid->w_high=tmp_wid->w_high;
my_wid->w_low=col;
my_wid->wids[0]=wid;
bcopy(&(tmp_wid->wids[0]),&(my_wid->wids[1]),(tmp_wid->w_high-tmp_wid->w_low)*sizeof(unsigned short));
my_wid->prev=tmp_wid->prev;
my_wid->next=tmp_wid->next;
if(my_wid->next)
my_wid->next->prev=my_wid;
else
wid_end=my_wid;
if(my_wid->prev)
my_wid->prev->next=my_wid;
else
wid_beg=my_wid;
free(tmp_wid);
return;
}
my_wid=(struct width *)ck_malloc(sizeof(struct width));
my_wid->w_high=col;
my_wid->w_low=col;
my_wid->wids[0]=wid;
my_wid->next=tmp_wid;
my_wid->prev=tmp_wid->prev;
tmp_wid->prev=my_wid;
if(my_wid->prev)
my_wid->prev->next=my_wid;
else
wid_beg=my_wid;
return;
}
unsigned short
next_widths FUN2(CELLREF *,c1, CELLREF *,c2)
{
static struct width *wid;
static int n;
static int nhi;
unsigned short ret;
int m;
if(c1==0) {
wid=wid_beg;
n=0;
if(wid)
nhi=wid->w_high-wid->w_low;
return 0;
}
for(;wid;wid=wid->next,n=0,nhi=wid->w_high-wid->w_low) {
for(;n<=nhi;n++) {
if(wid->wids[n]==0)
continue;
ret=wid->wids[n];
for(m=n+1;m<=nhi && wid->wids[m]==ret;m++)
;
*c1=wid->w_low+n;
*c2=wid->w_low+m-1;
n=m;
if(n>nhi) {
n=0;
wid=wid->next;
if(wid)
nhi=wid->w_high-wid->w_low;
}
return ret;
}
}
return 0;
}
void
flush_widths FUN0()
{
struct width *w,*wn;
for(w=wid_beg;w;w=wn) {
wn=w->next;
free(w);
}
wid_beg=0;
}
void
shift_widths FUN1(int, over)
{
struct width *w, *wtmp;
for(w=wid_beg;w;w=w->next) {
if(over<0 && w->w_low<= -over) {
if(w->w_high<=MIN_COL-over) {
if(w->prev)
w->prev->next=w->next;
else
wid_beg=w->next;
if(w->next)
w->next=w->prev;
else
wid_end=w->prev;
} else {
wtmp=ck_malloc(sizeof(struct width)+(w->w_high+over-MIN_COL)*sizeof(unsigned short));
if(w->next) {
wtmp->next=w->next;
w->next->prev=wtmp;
} else
wid_end=wtmp;
if(w->prev) {
wtmp->prev=w->prev;
w->prev->next=wtmp;
} else
wid_beg=wtmp;
wtmp->w_low=MIN_COL;
wtmp->w_high=w->w_high+over;
bcopy(&(w->wids[MIN_COL-over-w->w_low]),&(wtmp->wids[0]),(wtmp->w_high+1-wtmp->w_low)*sizeof(unsigned short));
}
free(w);
} else if(over>0 && w->w_high>=MAX_COL-over) {
if(w->w_low>=MAX_COL-over) {
if(w->prev)
w->prev->next=w->next;
else
wid_beg=w->next;
if(w->next)
w->next=w->prev;
else
wid_end=w->prev;
free(w);
} else {
w->w_high=MAX_COL;
w->w_low+=over;
w=ck_realloc(w,sizeof(struct width)+(w->w_high-w->w_low)*sizeof(unsigned short));
if(w->next)
w->next->prev=w;
else
wid_end=w;
if(w->prev)
w->prev->next=w;
else
wid_beg=w;
}
} else {
w->w_low+=over;
w->w_high+=over;
}
}
}
/* Structures/vars/functions for dealing with formatting floating-point
numbers, etc */
struct user_fmt {
char *p_hdr,*n_hdr;
char *p_trl,*n_trl;
char *zero,*comma,*decpt;
unsigned char prec;
double scale;
};
/* Routines for formatting cell values */
static char *pr_flt EXT3(double, struct user_fmt *, int);
static char *pr_int EXT3(long, struct user_fmt *, int);
struct user_fmt dol = {
"$","($", 0,")", "$0",",", ".", PRC_FLT, 1 };
struct user_fmt cma = {
0, "(", 0,")", "0", ",", ".", PRC_FLT, 1 };
struct user_fmt pct = {
0, "-", "%","%", "0%", 0, ".", PRC_FLT, 100 };
struct user_fmt fxt = {
0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 };
/* Variables */
struct user_fmt u[16] = {
{ 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
{ 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
{ 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
{ 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
{ 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
{ 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
{ 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
{ 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
{ 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
{ 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
{ 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
{ 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
{ 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
{ 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
{ 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
{ 0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1 },
};
/* Turn a floating-point number into the canonical text form. This scribbles
on print_buf */
char *
flt_to_str FUN1(double, val)
{
double f;
extern double fabs();
if(val==__plinf)
return iname;
if(val==__neinf)
return mname;
f=fabs(val);
if(f>=1e6 || (f>0 && f<=9.9999e-6)) {
sprintf(print_buf,"%e",val);
return print_buf;
}
return pr_flt(val,&fxt,PRC_FLT);
}
/* create the human-readable version of the contents of a cell
This scribbles on print-buf bigtime */
char *
print_cell FUN1(CELL *,cp)
{
int j;
int p;
long num;
static char zeroes[] = "000000000000000";
j=GET_FMT(cp);
if(j==FMT_DEF)
j=default_fmt;
if(j==FMT_HID || GET_TYP(cp)==0)
return "";
if(GET_TYP(cp)==TYP_STR)
return cp->cell_str;
if(GET_TYP(cp)==TYP_BOL) {
#ifdef TEST
if(cp->cell_bol<0 || cp->cell_bol>1)
panic("Bool %d out of range",cp->cell_bol);
#endif
return bname[cp->cell_bol];
}
if(GET_TYP(cp)==TYP_ERR) {
#ifdef TEST
if(cp->cell_err>ERR_MAX || cp->cell_err<0)
panic("Error %d out of range",cp->cell_err);
#endif
return ename[cp->cell_err];
}
if(GET_TYP(cp)==TYP_FLT) {
p=GET_PRC(j);
switch(j|PRC_FLT) {
case FMT_GPH:
if(cp->cell_flt<0) {
j='-';
num = -(cp->cell_flt);
} else if(cp->cell_flt>=1) {
j='+';
num= (cp->cell_flt);
} else {
j='0';
num=1;
}
graph:
if(num>=sizeof(print_buf)) {
error_msg("Cannot graph %d '%c'",p,j);
num=sizeof(print_buf)-1;
}
print_buf[num]='\0';
while(--num>=0)
print_buf[num]=j;
return print_buf;
case FMT_USR:
return pr_flt(cp->cell_flt,&u[p],u[p].prec);
case FMT_GEN:
{
double f;
extern double fabs();
f=fabs(cp->cell_flt);
if(f>=1e6 || (f>0 && f<=9.9999e-6))
goto handle_exp;
return pr_flt(cp->cell_flt,&fxt,p);
}
case FMT_DOL:
return pr_flt(cp->cell_flt,&dol,p);
case FMT_CMA:
return pr_flt(cp->cell_flt,&cma,p);
case FMT_PCT:
return pr_flt(cp->cell_flt,&pct,p);
case FMT_FXT:
return pr_flt(cp->cell_flt,&fxt,p);
case FMT_EXP:
handle_exp:
if(cp->cell_flt==__plinf)
return iname;
if(cp->cell_flt==__neinf)
return mname;
if(p==PRC_FLT)
sprintf(print_buf,"%e",cp->cell_flt);
else
sprintf(print_buf,"%.*e",p,cp->cell_flt);
return print_buf;
#ifdef TEST
default:
panic("Unknown format %d",j);
return 0;
#endif
}
}
if(GET_TYP(cp)==TYP_INT) {
p=GET_PRC(j);
switch(j|PRC_FLT) {
case FMT_GPH:
if(cp->cell_int<0) {
j='-';
num = -(cp->cell_int);
} else if(cp->cell_int>=1) {
j='+';
num = (cp->cell_int);
} else {
j='0';
num = 1;
}
goto graph;
case FMT_USR:
return pr_int(cp->cell_int,&u[p],u[p].prec);
case FMT_GEN:
sprintf(print_buf,"%ld",cp->cell_int);
return print_buf;
case FMT_DOL:
return pr_int(cp->cell_int,&dol,p);
case FMT_CMA:
return pr_int(cp->cell_int,&cma,p);
case FMT_PCT:
return pr_int(cp->cell_int,&pct,p);
case FMT_FXT:
if(p!=PRC_FLT && p!=0)
sprintf(print_buf,"%ld.%.*s",cp->cell_int,p,zeroes);
else
sprintf(print_buf,"%ld",cp->cell_int);
return print_buf;
case FMT_EXP:
if(p!=PRC_FLT)
sprintf(print_buf,"%.*e",p,(double)(cp->cell_int));
else
sprintf(print_buf,"%e",(double)(cp->cell_int));
return print_buf;
#ifdef TEST
default:
panic("Unknown format %d",j);
return 0;
#endif
}
}
#ifdef TEST
panic("Unknown cell type %d",GET_TYP(cp));
#endif
return 0;
}
/* Return the value of ROW,COL in a human-readable fashion
In paticular, strings have "" around them, and are \\ed
*/
char *
cell_value_string FUN2(CELLREF, row, CELLREF, col)
{
CELL *cp;
extern char *bname[];
extern char print_buf[];
extern char *flt_to_str();
extern char *backslash_a_string();
cp=find_cell(row,col);
if(!cp || !GET_TYP(cp))
return "";
switch(GET_TYP(cp)) {
case TYP_FLT:
return flt_to_str(cp->cell_flt);
case TYP_INT:
sprintf(print_buf,"%ld",cp->cell_int);
return print_buf;
case TYP_STR:
return backslash_a_string(cp->cell_str,1);
case TYP_BOL:
return bname[cp->cell_bol];
case TYP_ERR:
return ename[cp->cell_err];
#ifdef TEST
default:
panic("unknown type %d in cell_value_string",GET_TYP(cp));
#endif
}
return 0;
}
static char *
pr_int FUN3(long,val, struct user_fmt *,fmt, int,prec)
{
char *pf, *pff, *pt;
long int n;
int nn=0;
pt= &print_buf[sizeof(print_buf)-1];
*pt='\0';
n= fmt->scale * ((val<0) ? -val : val);
if(n==0)
return fmt->zero ? fmt->zero : "";
pf=pff= (val<0) ? fmt->n_trl : fmt->p_trl;
if(pf && *pf) {
while(*pf)
pf++;
do
*--pt= *--pf;
while(pf!=pff);
}
if(prec!=PRC_FLT && prec!=0) {
while(prec-->0)
*--pt='0';
pf=pff=fmt->decpt;
if(pf) {
while(*pf)
pf++;
do *--pt= *--pf;
while(pf!=pff);
}
/* *--pt='.'; */
}
do {
*--pt= (n%10)+'0';
n/=10;
if(nn++==2 && n>0) {
if(fmt->comma && *(fmt->comma)) {
for(pf=pff=fmt->comma;*pf;pf++)
;
do *--pt= *--pf;
while(pf!=pff);
}
nn=0;
}
} while(n>0);
pf=pff= (val<0) ? fmt->n_hdr : fmt->p_hdr;
if(pf && *pf) {
while(*pf)
pf++;
do *--pt= *--pf;
while(pf!=pff);
}
return pt;
}
static char *
pr_flt FUN3(double,val, struct user_fmt *,fmt, int,prec)
{
char *iptr;
char *fptr;
char *pptr;
char *pf,*pff;
double fract, integer, tmpval;
int n;
int isneg;
int comlen;
val*=fmt->scale;
if(val==__plinf)
return iname;
if(val==__neinf)
return mname;
if(val!=val)
return nname;
iptr= &print_buf[BIGFLT];
fptr= &print_buf[BIGFLT];
if(val<0) {
isneg=1;
val = -val;
} else
isneg=0;
if(val==0)
return fmt->zero ? fmt->zero : "";
comlen=0;
if(fmt->comma && *(fmt->comma))
for(pf=fmt->comma;*pf;comlen++,pf++)
;
fract=modf(val,&integer);
n=0;
do {
if(iptr< &print_buf[comlen])
return numb_oflo;
tmpval=modf(integer/10,&integer);
*--iptr='0'+(int)((tmpval+.01)*10);
if(n++==2 && integer) {
n=0;
if(comlen) {
pff=fmt->comma;
pf=pff+comlen;
do *--iptr= *--pf;
while(pf!=pff);
}
}
} while(integer);
if(prec) {
int p1;
p1= (prec==PRC_FLT) ? 15 : (prec>0) ? prec : -prec;
pf=fmt->decpt;
while(pf && *pf)
*fptr++= *pf++;
/* *fptr++='.'; */
if(fract) {
do {
fract = modf(fract * 10,&tmpval);
*fptr++ = '0' + (int)tmpval;
} while (--p1 && fract);
}
if(prec>0 && prec!=PRC_FLT)
while(p1--)
*fptr++='0';
else {
while(fptr[-1]=='0')
--fptr;
while(!isdigit(fptr[-1]))
--fptr;
*fptr='\0';
}
}
if(fract) {
(void)modf(fract * 10, &tmpval);
if(tmpval>4) {
iptr[-1]='0';
for(pptr=fptr-1;;--pptr) {
if(!isdigit(*pptr))
continue;
else if(*pptr=='9') {
if(pptr==fptr-1 && pptr>&print_buf[BIGFLT] && (prec<0 || prec==PRC_FLT)) {
--fptr;
while(!isdigit(pptr[-1])) {
--fptr;
--pptr;
}
*pptr='\0';
} else
*pptr='0';
} else {
(*pptr)++;
break;
}
}
if(pptr<iptr) {
--iptr;
if(n==3) {
n= *iptr++;
for(pf=pff=fmt->comma;*pf;pf++)
;
do *--iptr= *--pf;
while(pf!=pff);
*--iptr=n;
}
}
}
}
pf=pff= (isneg) ? fmt->n_hdr : fmt->p_hdr;
if(pf && *pf) {
while(*pf)
pf++;
do *--iptr= *--pf;
while(pf!=pff);
}
pf=(isneg) ? fmt->n_trl : fmt->p_trl;
while(pf && *pf)
*fptr++ = *pf++;
*fptr=0;
return iptr;
}
char *
adjust_prc FUN5(char *,oldp, CELL *,cp, int,width, int,smallwid, int,just)
{
int fmt;
int prc;
struct user_fmt *ufmt;
char *bptr;
char *eptr;
int len;
fmt=GET_FMT(cp);
if(fmt==FMT_DEF)
fmt=default_fmt;
prc=GET_PRC(fmt);
switch(fmt|PRC_FLT) {
case FMT_GPH:
case FMT_HID:
return numb_oflo;
case FMT_DOL:
ufmt= &dol;
goto deal_fmt;
case FMT_CMA:
ufmt= &cma;
goto deal_fmt;
case FMT_PCT:
ufmt= &cma;
goto deal_fmt;
case FMT_FXT:
ufmt= &fxt;
goto deal_fmt;
case FMT_USR:
ufmt= &u[prc];
prc=ufmt->prec;
goto deal_fmt;
case FMT_GEN:
if(prc!=PRC_FLT)
return numb_oflo;
if(index(oldp,'e') || !index(oldp,'.'))
goto handle_exp;
ufmt= &fxt;
prc=PRC_FLT;
goto deal_fmt;
deal_fmt:
if(prc!=PRC_FLT)
return numb_oflo;
len=strlen(oldp);
bptr=strstr(oldp,ufmt->decpt);
if(!bptr)
return numb_oflo;
while(eptr=strstr(bptr+1,ufmt->decpt))
bptr=eptr;
if(width<bptr-oldp)
return numb_oflo;
if(bptr-oldp+strlen(ufmt->decpt)>=width)
prc=0;
else {
prc=width-(strlen(ufmt->decpt)+bptr-oldp);
}
bptr=pr_flt(cp->cell_flt,ufmt,-prc);
len=strlen(bptr);
if(len>width && prc>0) {
bptr=pr_flt(cp->cell_flt,ufmt,-(prc-1));
len=strlen(bptr);
}
if(len>width)
return numb_oflo;
break;
case FMT_EXP:
handle_exp:
{
double f;
extern double fabs EXT1(double);
f=fabs(cp->cell_flt);
if(f>9.99999e99 || f<1e-99)
len=width-7;
else /* if(f>9.9999999e9 || f<1e-9) */
len=width-6;
/* else
len=width-5; */
if(cp->cell_flt<0)
--len;
if(len>0) {
sprintf(oldp,"%.*e",len,cp->cell_flt);
len=strlen(oldp);
if(len<=width) {
bptr=oldp;
break;
}
}
}
return numb_oflo;
#ifdef TEST
default:
panic("Unknown format %d in adjust_prc()",fmt);
bptr=0;
len=0;
break;
#endif
}
/* If we get here, bptr points to a a string of len characters
(len<=width) that we want to output */
if(len<smallwid) {
if(just==JST_RGT || just==JST_CNT) {
int n;
n= (just==JST_RGT) ? smallwid-len : (1+smallwid-len)/2;
for(;;) {
bptr[len+n]=bptr[len];
if(len--==0)
break;
}
while(n-->=0)
bptr[n]=' ';
}
}
return bptr;
}
void
set_usr_stats FUN2(int,usr_n, char **,usr_buf)
{
int len;
int i;
char *p_in,*p_out;
len=0;
for(i=0;i<7;i++)
len+=strlen(usr_buf[i]);
u[usr_n].p_hdr=ck_malloc(len+7);
p_out=u[usr_n].p_hdr;
if(usr_buf[0][0]) {
p_in=usr_buf[0];
while(*p_out++= *p_in++)
;
} else
*p_out++='\0';
if(usr_buf[1][0]) {
p_in=usr_buf[1];
u[usr_n].n_hdr=p_out;
while(*p_out++= *p_in++)
;
} else
u[usr_n].n_hdr=0;
if(usr_buf[2][0]) {
p_in=usr_buf[2];
u[usr_n].p_trl=p_out;
while(*p_out++= *p_in++)
;
} else
u[usr_n].p_trl=0;
if(usr_buf[3][0]) {
p_in=usr_buf[3];
u[usr_n].n_trl=p_out;
while(*p_out++= *p_in++)
;
} else
u[usr_n].n_trl=0;
if(usr_buf[4][0]) {
p_in=usr_buf[4];
u[usr_n].zero=p_out;
while(*p_out++= *p_in++)
;
} else
u[usr_n].zero=0;
if(usr_buf[5][0]) {
p_in=usr_buf[5];
u[usr_n].comma=p_out;
while(*p_out++= *p_in++)
;
} else
u[usr_n].comma=0;
if(usr_buf[6][0]) {
p_in=usr_buf[6];
u[usr_n].decpt=p_out;
while(*p_out++= *p_in++)
;
} else
u[usr_n].decpt=0;
if(!stricmp(usr_buf[7],"float") || !stricmp(usr_buf[7],"f"))
u[usr_n].prec=15;
else
u[usr_n].prec=astol(&usr_buf[7]);
u[usr_n].scale=astof(&usr_buf[8]);
}
int
usr_set_fmts FUN0()
{
int n;
int ret = 0;
for(n=0;n<16;n++)
if(u[n].p_hdr)
ret|=1<<n;
return ret;
}
void
get_usr_stats FUN2(int,usr_num, char **,usr_buf)
{
static char buf1[30];
static char buf2[30];
static char NullStr[]="";
usr_buf[0]= u[usr_num].p_hdr ? u[usr_num].p_hdr : NullStr;
usr_buf[1]= u[usr_num].n_hdr ? u[usr_num].n_hdr : NullStr;
usr_buf[2]= u[usr_num].p_trl ? u[usr_num].p_trl : NullStr;
usr_buf[3]= u[usr_num].n_trl ? u[usr_num].n_trl : NullStr;
usr_buf[4]= u[usr_num].zero ? u[usr_num].zero : NullStr;
usr_buf[5]= u[usr_num].comma ? u[usr_num].comma : NullStr;
usr_buf[6]= u[usr_num].decpt ? u[usr_num].decpt : NullStr;
if(u[usr_num].prec==15)
usr_buf[7]="float";
else {
sprintf(buf1,"%u",u[usr_num].prec);
usr_buf[7]=buf1;
}
sprintf(buf2,"%.12g",u[usr_num].scale);
usr_buf[8]=buf2;
}
/* Functions for printing out the names of cells and ranges */
char *
cell_name FUN2(CELLREF,rr, CELLREF,cc)
{
static char strs[2][20];
static num = 0;
char *ptr;
num = num ? 0 : 1;
#ifdef A0_REFS
ptr= &strs[num][9];
sprintf(ptr,"%u",rr);
if(cc<MIN_COL+26)
*--ptr='A'-MIN_COL+cc;
else if(cc<MIN_COL+702) {
cc-=MIN_COL+26;
*--ptr='A'+cc%26;
*--ptr='A'+cc/26;
}
#if MAX_COL>702
else if(cc<MIN_COL+18278) {
cc-=MIN_COL+702;
*--ptr='A'+cc%26;
cc/=26;
*--ptr='A'+cc%26;
*--ptr='A'+cc/26;
} else {
cc-=MIN_COL+18278;
*--ptr='A'+cc%26;
cc/=26;
*--ptr='A'+cc%26;
cc/=26;
*--ptr='A'+cc%26;
*--ptr='A'+cc/26;
}
#else
else
panic("Col %u out of range in cell_name()",cc);
#endif
#else
ptr= &strs[num][0];
sprintf(ptr,"r%uc%u",rr,cc);
#endif
return ptr;
}
char *
range_name FUN1(struct rng *,rng)
{
CELLREF lr,lc,hr,hc;
static char buf[2][40];
static num;
char *ptr;
ptr= &buf[num][0];
num = num ? 0 : 1;
lr=rng->lr;
lc=rng->lc;
hr=rng->hr;
hc=rng->hc;
#ifdef A0_REFS
sprintf(ptr,"%s:%s",cell_name(lr,lc),cell_name(hr,hc));
return ptr;
#else
if(lr==hr && lc==hc)
sprintf(ptr,"r%uc%u",lr,lc);
else if(lr==hr && lc!=hc)
sprintf(ptr,"r%uc%u:%u",lr,lc,hc);
else if(lr!=hr && lc==hc)
sprintf(ptr,"r%u:%uc%u",lr,hr,lc);
else
sprintf(ptr,"r%u:%uc%u:%u",lr,hr,lc,hc);
return ptr;
#endif
}
#ifdef A0_REFS
char *
col_to_str FUN1(CELLREF, col)
{
static char strs[2][10];
static num;
char *ptr;
ptr= &strs[num][9];
num = num ? 0 : 1;
if(col<MIN_COL+26)
*--ptr='A'-MIN_COL+col;
else if(col<MIN_COL+702) {
col-=MIN_COL+26;
*--ptr='A'+col%26;
*--ptr='A'+col/26;
} else if(col<MIN_COL+18278) {
col-=MIN_COL+702;
*--ptr='A'+col%26;
col/=26;
*--ptr='A'+col%26;
*--ptr='A'+col/26;
} else {
col-=MIN_COL+18278;
*--ptr='A'+col%26;
col/=26;
*--ptr='A'+col%26;
col/=26;
*--ptr='A'+col%26;
*--ptr='A'+col/26;
}
return ptr;
}
#endif
void
clear_spreadsheet FUN0()
{
int n;
extern int default_jst;
extern int default_lock;
extern void flush_widths EXT0();
extern void flush_everything EXT0();
extern void flush_all_timers EXT0();
flush_everything();
flush_widths();
flush_all_timers();
for(n=0;n<16;n++) {
if(u[n].p_hdr) {
free(u[n].p_hdr);
u[n].p_hdr=0;
u[n].prec=PRC_FLT;
u[n].scale=1;
}
}
default_width=8;
default_jst=JST_LFT;
default_fmt=FMT_GEN;
default_lock=LCK_UNL;
}